// import { ChangeEvent } from "react";

// function App() {
//   function onChange(event: ChangeEvent<HTMLInputElement>) {
//     console.log(event.target.value);
//   }

//   return <input defaultValue={"guang"} onChange={onChange} />;
// }

// export default App;
//=======================
// import { useEffect, useRef } from "react";

// function App() {
//   const inputRef = useRef<HTMLInputElement>(null);

//   useEffect(() => {
//     setTimeout(() => {
//       console.log(inputRef.current?.value);
//     }, 2000);
//   }, []);

//   return <input defaultValue={"guang"} ref={inputRef} />;
// }

// export default App;

//=======================
// import { ChangeEvent, useState } from "react";

// function App() {
//   const [value, setValue] = useState("guang");

//   function onChange(event: ChangeEvent<HTMLInputElement>) {
//     console.log(event.target.value);
//     // setValue(event.target.value);
//   }

//   return <input value={value} onChange={onChange} />;
// }

// export default App;

//===============================

// import { ChangeEvent, useState } from "react";

// function App() {
//   const [value, setValue] = useState("guang");
//   console.log('render....');

//   function onChange(event: ChangeEvent<HTMLInputElement>) {
//     // console.log(event.target.value);
//     setValue(event.target.value);
//   }

//   return <input value={value} onChange={onChange} />;
// }

// export default App;
//================

// import { ChangeEvent } from "react";

// function App() {
//   console.log("render....");
//   function onChange(event: ChangeEvent<HTMLInputElement>) {
//     // console.log(event.target.value);
//   }

//   return <input defaultValue={"guang"} onChange={onChange} />;
// }

// export default App;

//================

// import { ChangeEvent, useState } from "react";

// function App() {
//   const [value, setValue] = useState("guang");

//   function onChange(event: ChangeEvent<HTMLInputElement>) {
//     console.log(event.target.value);
//     setValue(event.target.value.toUpperCase());
//   }

//   return <input value={value} onChange={onChange} />;
// }

// export default App;

//================

// import { ChangeEvent, useState } from "react";

// interface CalendarProps {
//   defaultValue?: Date;
//   onChange?: (date: Date) => void;
// }
// function Calendar(props: CalendarProps) {
//   const { defaultValue = new Date(), onChange } = props;

//   const [value, setValue] = useState(defaultValue);

//   function changeValue(date: Date) {
//     setValue(date);
//     onChange?.(date);
//   }

//   return (
//     <div>
//       {value.toLocaleDateString()}
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-1"));
//         }}
//       >
//         2023-5-1
//       </div>
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-2"));
//         }}
//       >
//         2023-5-2
//       </div>
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-3"));
//         }}
//       >
//         2023-5-3
//       </div>
//     </div>
//   );
// }

// function App() {
//   return (
//     <Calendar
//       defaultValue={new Date("2024-5-1")}
//       onChange={(date) => {
//         console.log(date.toLocaleDateString());
//       }}
//     />
//   );
// }

// export default App;
//================

// import { ChangeEvent, useEffect, useState } from "react";

// interface CalendarProps {
//   value: Date;
//   onChange?: (date: Date) => void;
// }
// function Calendar(props: CalendarProps) {
//   const { value, onChange } = props;

//   function changeValue(date: Date) {
//     onChange?.(date);
//   }

//   return (
//     <div>
//       {value.toLocaleDateString()}
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-1"));
//         }}
//       >
//         2023-5-1
//       </div>
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-2"));
//         }}
//       >
//         2023-5-2
//       </div>
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-3"));
//         }}
//       >
//         2023-5-3
//       </div>
//     </div>
//   );
// }

// function App() {
//   const [value, setValue] = useState(new Date("2024-5-1"));

//   return (
//     <Calendar
//       value={value}
//       onChange={(date) => {
//         console.log(date.toLocaleDateString());
//         setValue(date);
//       }}
//     />
//   );
// }

// export default App;
//==================

// import { useEffect, useRef, useState } from "react";

// interface CalendarProps {
//   value?: Date;
//   defaultValue?: Date;
//   onChange?: (date: Date) => void;
// }

// function Calendar(props: CalendarProps) {
//   const { value: propsValue, defaultValue, onChange } = props;

//   const [value, setValue] = useState(() => {
//     if (propsValue !== undefined) {
//       return propsValue;
//     } else {
//       return defaultValue;
//     }
//   });

//   const isFirstRender = useRef(true);

//   useEffect(() => {
//     if (propsValue === undefined && !isFirstRender.current) {
//       setValue(propsValue);
//     }
//     isFirstRender.current = false;
//   }, [propsValue]);

//   const mergedValue = propsValue === undefined ? value : propsValue;

//   function changeValue(date: Date) {
//     if (propsValue === undefined) {
//       setValue(date);
//     }
//     onChange?.(date);
//   }

//   return (
//     <div>
//       {mergedValue?.toLocaleDateString()}
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-1"));
//         }}
//       >
//         2023-5-1
//       </div>
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-2"));
//         }}
//       >
//         2023-5-2
//       </div>
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-3"));
//         }}
//       >
//         2023-5-3
//       </div>
//     </div>
//   );
// }

// function App() {
//   // return (
//   //   <Calendar
//   //     defaultValue={new Date("2024-5-1")}
//   //     onChange={(date) => {
//   //       console.log(date.toLocaleDateString());
//   //     }}
//   //   />
//   // );
//   const [value, setValue] = useState(new Date("2024-5-1"));
//   return (
//     <Calendar
//       value={value}
//       onChange={(date) => {
//         console.log(date.toLocaleDateString());
//         setValue(date)
//       }}
//     />
//   );

// }

// export default App;

//=========
// import { useEffect, useRef, useState } from "react";
// function useMergeState<T>(
//   defaultStateValue: T,
//   props?: {
//     defaultValue?: T;
//     value?: T;
//   }
// ): [T, React.Dispatch<React.SetStateAction<T>>] {
//   const { defaultValue, value: propsValue } = props || {};

//   const isFirstRender = useRef(true);

//   const [stateValue, setStateValue] = useState<T>(() => {
//     if (propsValue !== undefined) {
//       return propsValue!;
//     } else if (defaultValue !== undefined) {
//       return defaultValue!;
//     } else {
//       return defaultStateValue;
//     }
//   });

//   useEffect(() => {
//     if (propsValue === undefined && !isFirstRender.current) {
//       setStateValue(propsValue!);
//     }

//     isFirstRender.current = false;
//   }, [propsValue]);

//   const mergedValue = propsValue === undefined ? stateValue : propsValue;

//   return [mergedValue, setStateValue];
// }
// interface CalendarProps {
//   value?: Date;
//   defaultValue?: Date;
//   onChange?: (date: Date) => void;
// }

// function Calendar(props: CalendarProps) {
//   const { value: propsValue, defaultValue, onChange } = props;

//   const [mergedValue, setValue] = useMergeState(new Date(), {
//     value: propsValue,
//     defaultValue,
//   });

//   function changeValue(date: Date) {
//     if (propsValue === undefined) {
//       setValue(date);
//     }
//     onChange?.(date);
//   }

//   return (
//     <div>
//       {mergedValue?.toLocaleDateString()}
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-1"));
//         }}
//       >
//         2023-5-1
//       </div>
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-2"));
//         }}
//       >
//         2023-5-2
//       </div>
//       <div
//         onClick={() => {
//           changeValue(new Date("2024-5-3"));
//         }}
//       >
//         2023-5-3
//       </div>
//     </div>
//   );
// }

// function App() {
//   // return (
//   //   <Calendar
//   //     defaultValue={new Date("2024-5-1")}
//   //     onChange={(date) => {
//   //       console.log(date.toLocaleDateString());
//   //     }}
//   //   />
//   // );
//   const [value, setValue] = useState(new Date("2024-5-1"));
//   return (
//     <Calendar
//       value={value}
//       onChange={(date) => {
//         console.log(date.toLocaleDateString());
//         setValue(date);
//       }}
//     />
//   );
// }
// export default App;


//====================
import {
  SetStateAction,
  useCallback,
  useEffect,
  useRef,
  useState,
} from "react";

function useMergeState<T>(
  defaultStateValue: T,
  props?: {
    defaultValue?: T;
    value?: T;
    onChange?: (value: T) => void;
  }
): [T, React.Dispatch<React.SetStateAction<T>>] {
  const { defaultValue, value: propsValue, onChange } = props || {};

  const isFirstRender = useRef(true);

  const [stateValue, setStateValue] = useState<T>(() => {
    if (propsValue !== undefined) {
      return propsValue!;
    } else if (defaultValue !== undefined) {
      return defaultValue!;
    } else {
      return defaultStateValue;
    }
  });

  useEffect(() => {
    if (propsValue === undefined && !isFirstRender.current) {
      setStateValue(propsValue!);
    }

    isFirstRender.current = false;
  }, [propsValue]);

  const mergedValue = propsValue === undefined ? stateValue : propsValue;

  function isFunction(value: unknown): value is Function {
    return typeof value === "function";
  }

  const setState = useCallback(
    (value: SetStateAction<T>) => {
      let res = isFunction(value) ? value(stateValue) : value;

      if (propsValue === undefined) {
        setStateValue(res);
      }
      onChange?.(res);
    },
    [stateValue]
  );

  return [mergedValue, setState];
}

interface CalendarProps {
  value?: Date;
  defaultValue?: Date;
  onChange?: (date: Date) => void;
}

function Calendar(props: CalendarProps) {
  const { value: propsValue, defaultValue, onChange } = props;

  const [mergedValue, setValue] = useMergeState(new Date(), {
    value: propsValue,
    defaultValue,
    onChange,
  });

  return (
    <div>
      {mergedValue?.toLocaleDateString()}
      <div
        onClick={() => {
          setValue(new Date("2024-5-1"));
        }}
      >
        2023-5-1
      </div>
      <div
        onClick={() => {
          setValue(new Date("2024-5-2"));
        }}
      >
        2023-5-2
      </div>
      <div
        onClick={() => {
          setValue(new Date("2024-5-3"));
        }}
      >
        2023-5-3
      </div>
    </div>
  );
}

function App() {
  const [value, setValue] = useState(new Date("2024-5-1"));

  return (
    <Calendar
      value={value}
      onChange={(date) => {
        console.log(date.toLocaleDateString());
        setValue(date);
      }}
    />
  );
  // return <Calendar defaultValue={new Date('2024-5-1')} onChange={(date) => {
  //   console.log(date.toLocaleDateString());
  // }}/>
}

export default App;
